package scala.cookbook.akka

/**
  * Created by shichen on 2017/5/10.
  */

import akka.actor.Actor.Receive
import akka.actor._
import com.typesafe.scalalogging.Logger
import org.slf4j.LoggerFactory

case object Explode

class Number5 extends Actor {
  override def receive: Receive = {
    //新版本的异常不再自动重启actor ?
    case Explode => println("recv Explode"); throw new Exception("boom")
    case _ => println("number5 got a msg")
  }

  override def preStart(): Unit = {
    println("number5 is alive")
  }

  override def postStop(): Unit = {
    println("stopped")
  }

  override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
    println("preRestart")
    //super.preRestart(reason,message)
  }

  override def postRestart(reason: Throwable): Unit = {
    println("postRestart")
    //super.postRestart(reason)
  }
}


class Kenny extends Actor {
  println("enter kenny ctor")

  override def preStart(): Unit = {
    println("kenny:preStart")
  }

  override def postStop(): Unit = {
    //在完全停止之后会调用它
    println("kenny:postStop")
  }

  override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
    println("kenny:preRestart")
    println(s"\tMESSAGE:${message.getOrElse("")}")
    println(s"\tREASON: ${reason.getMessage}")
    super.preRestart(reason, message)
  }

  override def postRestart(reason: Throwable): Unit = {
    println("kenny: postRestart")
    println(s"\tREASON: ${reason.getMessage}")
    super.postRestart(reason)
  }

  override def receive: Receive = {
    case ForceRestart => throw new Exception("boom!")
    case _ => println("kenny received a msg")
  }
}

case object ForceRestart

//logger usage: http://blog.csdn.net/libing_thinking/article/details/41951215

object LifecycleDemo extends App {
  val logger = Logger(LoggerFactory.getLogger("test"))
  logger.debug("=============== debug log")

  val system = ActorSystem("lifecycledemo")
  val kenny = system.actorOf(Props[Kenny], name = "kenny")

  println("=============== sending kenny a simple msg")
  kenny ! "hello"
  Thread.sleep(1000)
  println("=============== make kenny restart")
  kenny ! ForceRestart
  Thread.sleep(1000)


  println("=============== stopping kenny")
  system.stop(kenny)
  println("=============== shut down the system actor")
  system.shutdown()


  def KillAnActor: Unit = {
    val sys = ActorSystem("killtest")
    val a = sys.actorOf(Props[Number5], name = "number5")
    a ! "hello"

    //a ! Kill
    a ! Explode
    println("calling shuwdown...")
    sys.shutdown()
  }
}

/*
22:42:25.971 [main] DEBUG test - debug log
sending kenny a simple msg
enter kenny ctor
kenny:preStart
kenny received a msg
make kenny restart
kenny:preRestart  异常使之自动重启
 MESSAGE:ForceRestart
 REASON: boom!
kenny:postStop
enter kenny ctor 再一次构造
kenny: postRestart  重启后调用
 REASON: boom!
kenny:preStart actor 启动前调用
[ERROR] [05/22/2017 22:42:27.517] [lifecycledemo-akka.actor.default-dispatcher-5] [akka://lifecycledemo/user/kenny] boom!
java.lang.Exception: boom!
	at cs.akka.Kenny$$anonfun$receive$1.applyOrElse(13_ActorTest.scala:38)
	at akka.actor.Actor$class.aroundReceive(Actor.scala:465)
	at cs.akka.Kenny.aroundReceive(13_ActorTest.scala:12)
	at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516)
	at akka.actor.ActorCell.invoke(ActorCell.scala:487)
	at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:254)
	at akka.dispatch.Mailbox.run(Mailbox.scala:221)
	at akka.dispatch.Mailbox.exec(Mailbox.scala:231)
	at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
	at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
	at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
	at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

stopping kenny
shut down the system actor
kenny:postStop
[INFO] [05/22/2017 22:42:28.517] [lifecycledemo-akka.actor.default-dispatcher-2] [akka://lifecycledemo/user/kenny] Message [akka.dispatch.sysmsg.Terminate] from Actor[akka://lifecycledemo/user/kenny#596331394] to Actor[akka://lifecycledemo/user/kenny#596331394] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

Process finished with exit code 0

 */
